package com.jt.www.admin.order_pc.controller;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jt.www.admin.order_pc.service.ApplicationFormService;
import com.jt.www.admin.order_pc.service.ExportConfigService;
import com.jt.www.annotations.AddHeader;
import com.jt.www.domain.po.ApplicationFileInfoEntity;
import com.jt.www.domain.po.ExportConfigEntity;
import com.jt.www.domain.vo.EduPolicyBean;
import com.jt.www.enums.extend.ExcelDownFileEnum;
import com.jt.www.enums.extend.SchoolNatureEnum;
import com.jt.www.enums.issue.AppStatusEnum;
import com.jt.www.enums.issue.FinanceStatusEnum;
import com.jt.www.enums.issue.PolicyStatusEnum;
import com.jt.www.enums.issue.RenewalEnum;
import com.jt.www.model.param.endorse.AppDetailProParam;
import com.jt.www.model.remote.ins.EduPolicyStatisticsVo;
import com.jt.www.model.remote.ins.InsManagerResultVO;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.model.reps.ResponseData;
import com.jt.www.model.vo.*;
import com.jt.www.util.DateUtils;
import com.jt.www.util.excel.CsvExportUtil;
import com.jt.www.util.excel.ExcelUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.sf.jxls.transformer.XLSTransformer;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @ProjectName: edu-service
 * @ClassName: ApplicationFormController
 * @Author: shalongteng
 * @Description: ${description}
 * @Date: 2019-06-19 14:03
 * @Version: 1.0
 */
@Api(value = "查询投保单列表", tags = {"APPLICATION-API"}, description = "查询投保单列表接口")
@RestController
@RequestMapping(value = "/application/v1")
public class ApplicationFormController {

    public static final Logger log = LoggerFactory.getLogger(ApplicationFormController.class);
    @Autowired
    private ApplicationFormService applicationFormService;
    @Autowired
    private ExportConfigService exportConfigService;

    /**
     * @Description: 查询投保单列表
     * @Param: applicationFormVo
     * @return: InsResultVO
     * @Author: shalongteng
     * @Date: 2019-06-19
     */
    @ApiOperation(value = "查询投保单列表", httpMethod = "POST")
    @PostMapping(value = "/appilications", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseData findApplicationForm(@RequestBody InsManagerQo insManagerQo, HttpServletRequest request) throws Exception {
        String findCode = "EDU_" + System.currentTimeMillis();
        log.debug("{}查询投保单列表开始时间{}", findCode, DateUtils.format(new Date(), DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS_SSS));
        ResponseData res = applicationFormService.findApplicationForm(insManagerQo, findCode, false);
        log.debug("{}查询投保单列表开始时间{}", findCode, DateUtils.format(new Date(), DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS_SSS));
        return res;
    }


    /*
     *  统计投保单金额以及人数
     * @Author xq.wu
     * @Date 13:38 2020/4/16
     * @Param [insManagerQo]
     * @return org.springframework.http.ResponseEntity<?>
     **/
    @ApiOperation(value = "统计投保单金额以及人数", httpMethod = "POST")
    @PostMapping(value = "/statisticsAppilications", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public EduPolicyStatisticsVo statisticsAppilications(@RequestBody InsManagerQo insManagerQo) throws Exception {
        String findCode = "EDU_" + System.currentTimeMillis();
        return applicationFormService.statisticsAppilications(insManagerQo, findCode);
    }


    /*
     *  查询报文重发列表
     * @Author xq.wu
     * @Date 9:52 2019/10/25
     * @Param [insManagerQo]
     * @return org.springframework.http.ResponseEntity<com.jt.www.model.reps.GenericListResponse<com.jt.www.model.remote.ins.InsManagerResultVO>>
     **/
    @ApiOperation(value = "查询报文重发列表", httpMethod = "POST")
    @PostMapping(value = "/queryIssueList", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity findApplicationForm(@RequestBody IssueRetransQo issueRetransQo) throws Exception {
        PageInfo result = applicationFormService.findIssueList(issueRetransQo);
        return GenericListResponse.listAndCount(result.getList(), result.getTotal());
    }

    @ApiOperation(value = "导出投保单列表(作废)", notes = "统计结果并下载")
    @GetMapping(value = "/downAppList2", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public void downAppList2(InsManagerQo insManagerQo, HttpServletResponse response, HttpServletRequest request) {
        String findCode = "EDU_" + System.currentTimeMillis();
        //解析结果
        try {
            log.debug("{}导出投保单列表开始", findCode);
            boolean addSuccess = applicationFormService.findApplicationFormAddUserInfo(insManagerQo, findCode);
            List appList;
            if (addSuccess) {
                appList = applicationFormService.downAppList(insManagerQo, findCode);
            } else {
                appList = Lists.newArrayList();
            }

            log.debug("{}导出投保单checkStatus开始时间:{}", findCode, DateUtils.format(new Date(), DateUtils.DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS_SSS));
            checkStatus(appList, insManagerQo);
            ExcelUtils.checkNull(appList);
            Map<String, List<InsManagerResultVO>> beanParams = Maps.newHashMap();
            log.debug("{}导出投保单列表共查询出{}条数据", findCode, appList.size());

            beanParams.put("items", appList);
            //模板位置
            String path = ExcelDownFileEnum.getFilePath(insManagerQo.getChannelType(), insManagerQo.getProductCode());

            Resource resource = new ClassPathResource(path);

            XLSTransformer transformer = new XLSTransformer();
            InputStream inputStream = resource.getInputStream();
            transformer.setJexlInnerCollectionsAccess(true);

            Workbook wb = transformer.transformXLS(inputStream, beanParams);
            String fileName = "投保单列表.xls";
            ExcelUtils.compParam(fileName, response, request);
            ServletOutputStream outputStream = response.getOutputStream();
            wb.write(outputStream);
            outputStream.flush();
            inputStream.close();
            outputStream.close();
            log.debug("{}导出投保单列表结束", findCode);
        } catch (Exception e) {
            log.error("投保单列表导出失败!入参:" + JSON.toJSON(insManagerQo), e);
        }
    }

    private void checkStatus(List<InsManagerResultVO> appList, InsManagerQo insManagerQo) {

        if (appList != null && appList.size() > 0) {

            for (InsManagerResultVO insManagerResultVO : appList) {
                // 处理出单时间
                String issueDate = insManagerResultVO.getIssueDate();
                if (!StringUtils.isEmpty(issueDate)) {
                    issueDate = issueDate.substring(0, 19);
                    insManagerResultVO.setIssueDate(issueDate);
                }

                // 处理保费到账时间
                String payDate = insManagerResultVO.getPayDate();
                if (!StringUtils.isEmpty(payDate)) {
                    payDate = payDate.substring(0, 19);
                    insManagerResultVO.setPayDate(payDate);
                }

                //保单状态
                PolicyStatusEnum policyStatusEnum = PolicyStatusEnum.getEnumByCode(insManagerResultVO.getPolicyStatus());
                //财务状态
                FinanceStatusEnum financeStatusEnum = FinanceStatusEnum.getEnumByCode(insManagerResultVO.getFinanceStatus());

                // 处理投保单状态
                //已退保或是已失效
                if (policyStatusEnum.equals(PolicyStatusEnum.PS_00)
                        || policyStatusEnum.equals(PolicyStatusEnum.PS_01)) {
                    insManagerResultVO.setAppStatus(policyStatusEnum.getDesc());
                } else if (("02".equals(insManagerQo.getChannelType()) || "02,0001".equals(insManagerQo.getChannelType()))
                        && financeStatusEnum.equals(FinanceStatusEnum.FS_00)) {
                    //我学保未支付 投保单状态为待支付
                    insManagerResultVO.setAppStatus(AppStatusEnum.AS_98.getDesc());
                } else {
                    insManagerResultVO.setAppStatus(AppStatusEnum.getEnumByCode(insManagerResultVO.getAppStatus()).getDesc());
                }
                // 处理财务状态
                insManagerResultVO.setFinanceStatus(financeStatusEnum.getDesc());
                // 投保类型
                insManagerResultVO.setRenewal(RenewalEnum.getDescByCode(insManagerResultVO.getRenewal()));

                insManagerResultVO.setHolderSchoolNature(StringUtils.isNotBlank(insManagerResultVO.getHolderSchoolNature()) ? SchoolNatureEnum.getMsgByCode(insManagerResultVO.getHolderSchoolNature()) : "");
                insManagerResultVO.setInsuredSchoolNature(StringUtils.isNotBlank(insManagerResultVO.getInsuredSchoolNature()) ? SchoolNatureEnum.getMsgByCode(insManagerResultVO.getInsuredSchoolNature()) : "");
            }

        }

    }


    @ApiOperation(value = "下载投保单生成PDF文件", httpMethod = "GET")
    @GetMapping(value = "/downAppFormToPDF/{applicationFormCode}", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public void downAppFormToPDF(HttpServletResponse response,
                                 @ApiParam(value = "投保单号", required = true) @PathVariable String applicationFormCode) throws IOException {
        try {
            applicationFormService.downAppFormToPDF(applicationFormCode);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @AddHeader
    @ApiOperation(value = "在线查询", httpMethod = "POST")
    @PostMapping(value = "/online_query", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseEntity<?> onlineQuery(@RequestBody EduPolicyBean eduPolicyBean) {
        try {
            return GenericDataResponse.okWithData(applicationFormService.onlineQuery(eduPolicyBean));
        } catch (Exception e) {
            e.printStackTrace();
            return GenericDataResponse.errorWithMsg(e.getMessage());
        }
    }

    /**
     * 查询投保单列表(案件关联保单时使用)
     *
     * @param appForCaseQo
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "查询投保单列表(案件关联保单时使用)", httpMethod = "POST")
    @PostMapping(value = "/appilicationsForCase", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<?> appilicationsForCase(@RequestBody AppForCaseQo appForCaseQo) throws Exception {
        try {
            return GenericDataResponse.okWithData(applicationFormService.appilicationsForCase(appForCaseQo));
        } catch (Exception e) {
            e.printStackTrace();
            return GenericDataResponse.errorWithMsg(e.getMessage());
        }
    }

    /**
     * 查询被保险人信息(案件关联保单时使用)
     *
     * @param insuredForCaseQo
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "查询被保险人信息(案件关联保单时使用)", httpMethod = "POST")
    @PostMapping(value = "/insuredForCase", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<?> insuredForCase(@RequestBody InsuredForCaseQo insuredForCaseQo) throws Exception {
        try {
            InsuredForCaseVO vo = applicationFormService.insuredForCase(insuredForCaseQo);
            if (vo != null) {
                return GenericDataResponse.okWithData(vo);
            } else {
                return GenericDataResponse.errorWithMsg("未查询到被保险人信息");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return GenericDataResponse.errorWithMsg(e.getMessage());
        }
    }


    @ApiOperation(value = "投保补录", httpMethod = "POST")
    @PostMapping(value = "/postRecorded", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<?> postRecorded(
            @ApiParam(name = "excelFile", value = "补录清单excel", required = true) MultipartFile excelFile) {
        //补录
        return GenericDataResponse.okWithData(applicationFormService.postRecorded(excelFile));
    }


    @ApiOperation(value = "根据投保单号查询失败的跟单公司", httpMethod = "POST")
    @PostMapping(value = "/getBackPolicyNoError", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public ResponseData getBackPolicyNoError(@RequestBody AppDetailProParam param) {
        ResponseData responseData = null;
        try {
            responseData = applicationFormService.getBackPolicyNoError(param);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return responseData;
    }


    /**
     * 根据投保单号查询出单失败原因
     *
     * @param applicationFormCode
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "查询报文失败原因", httpMethod = "GET")
    @GetMapping(value = "/getErrorIssue", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseData getErrorIssue(
            @ApiParam(name = "applicationFormCode", value = "投保单号", required = true) @RequestParam(value = "applicationFormCode") String applicationFormCode) throws Exception {
        ResponseData errorIssue = applicationFormService.getErrorIssue(applicationFormCode);
        return errorIssue;
    }

    @ApiOperation(value = "保存投保单清单文件信息", httpMethod = "POST")
    @PostMapping(value = "/saveApplicationFileInfo", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<?> saveApplicationFileInfo(@RequestBody List<ApplicationFileInfoEntity> entities) throws Exception {
        return applicationFormService.saveApplicationFileInfo(entities);
    }

    @ApiOperation(value = "根据投保单号查询已上传清单人数总和", httpMethod = "GET")
    @GetMapping(value = "/getInsuredNumByAppCode", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<?> getInsuredNumByAppCode(@RequestParam("applicationFormCode") String applicationFormCode) throws Exception {
        return applicationFormService.getInsuredNumByAppCode(applicationFormCode);
    }


    @ApiOperation(value = "导出投保单列表（新）", notes = "统计结果并下载")
    @GetMapping(value = "/downAppList", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
    public void downAppList(InsManagerQo insManagerQo, HttpServletResponse response, HttpServletRequest request) {
        String findCode = "EDU_" + System.currentTimeMillis();
        OutputStream os = null;
        String fileName = "投保单列表";
        try {

            //查询导出配置
            ExportConfigEntity exportConfigEntity = exportConfigService.getExportConfig(insManagerQo.getChannelType(), insManagerQo.getProductCode());
            fileName = exportConfigEntity.getFileName();

            os = response.getOutputStream();
            CsvExportUtil.responseSetProperties(fileName, response);
            //模板位置
            String titles = exportConfigEntity.getTitles();
            CsvExportUtil.setTitles(titles, os);
            List appList;
            int pn = 1;
            insManagerQo.setPn(pn);
            insManagerQo.setPs(CsvExportUtil.MAX_PAGE_SIZE);
            String[] keyArr = exportConfigEntity.getKeyArr().split(",");
            boolean addSuccess = applicationFormService.findApplicationFormAddUserInfo(insManagerQo, findCode);
            if (addSuccess) {
                while (CollectionUtils.isNotEmpty(appList = applicationFormService.downAppList(insManagerQo, findCode))) {
                    checkStatus(appList, insManagerQo);
                    CsvExportUtil.doExport(appList, keyArr, os);
                    insManagerQo.setPn(++pn);
                    if (insManagerQo.getPs() > appList.size()) {
                        break;
                    }
                }
            }
        } catch (Exception e) {
            log.error("{}导出{}发生错误:", findCode, fileName, e);
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                }
            }
        }

    }


}
